#ifndef QLIB_HEADER_ARRAY
#define QLIB_HEADER_ARRAY

#include <vector>
#include "qlib/core/vec2.h"

namespace qlib {
template <typename T>
using Array = std::vector<T>;

using Vec2dArray = std::vector<Vec2d>;
using Vec2iArray = std::vector<Vec2i>;
using VecdArray = std::vector<double>;

template <typename T>
struct Gds_Array {
  uint64_t capacity = 0;
  uint64_t count = 0;
  T* items = NULL;
};

template <typename T>
size_t array_index(const Array<T> arr, const T& item) {
  auto it = arr.begin();
  while (it != arr.end()) {
    if (*it == item) {
      return it - arr.begin();
    }
    it++;
  }
  return arr.size();
}

template <typename T>
bool array_contains(const Array<T>& arr, const T& item) {
  return array_index(arr, item) < arr.size();
}

template <typename T>
void array_insert(Array<T>& arr, uint64_t index, const T& item) {
  arr.insert(arr.begin() + index, item);
}

template <typename T>
void array_remove_unordered(Array<T>& arr, uint64_t index) {
  arr[index] = arr.back();
  arr.pop_back();
}

template <typename T>
void array_remove(Array<T>& arr, uint64_t index) {
  if (arr.empty())
    return;
  if (index < arr.size())
    arr.erase(arr.begin() + index);
}

template <typename T>
bool array_remove_item(Array<T>& arr, const T& item) {
  uint64_t i = array_index(arr, item);
  if (i == arr.size())
    return false;
  array_remove(arr, i);
  return true;
}

template <typename T>
int array_ensure_slots(Array<T>& arr, uint64_t free_slots) {
  int old_size = arr.size();
  arr.resize(arr.size() + free_slots);
  return old_size;
}

template <typename T>
void array_extend(Array<T>& arr, const Array<T>& src) {
  arr.insert(arr.end(), src.begin(), src.end());
}
}  // namespace qlib

#endif